package zhan.interceptor;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.log4j.Logger;
import zhan.redis.RedisUtil;

import java.util.ArrayList;
import java.util.List;

public class RedisInterceptor implements MethodInterceptor {


    public static final Logger log = Logger.getLogger(RedisInterceptor.class);
    private RedisUtil redisUtil;
    private List<String> targetNamesList; // 禁用缓存的类名列表
    private List<String> methodNamesList; // 禁用缓存的方法列表
    private String defaultCacheExpireTime; // 缓存默认的过期时间

    /**
     * 初始化时读取不需要加入缓存的方法名和类名
     */
    public RedisInterceptor() {

        try {
            String[] targetName = {};
            String[] methodName = {};

            //创建list
            targetNamesList = new ArrayList<String>(targetName.length);
            methodNamesList = new ArrayList<String>(methodName.length);
            Integer maxLen = targetName.length > methodName.length ? targetName.length : methodName.length;

            //将类名，方法名加到list中
            for (int i = 0; i < maxLen; i++) {

                if (i < targetName.length) {
                    targetNamesList.add(targetName[i]);
                }
                if (i < methodName.length) {
                    methodNamesList.add(methodName[i]);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        log.info("-----------进入RedisInterceptor 自定义拦截器------------------");
        Object value = null;

        String targetName = invocation.getThis().getClass().getName();
        String methodName = invocation.getMethod().getName();

        log.info(targetName + "-----------------" + methodName);
        if (!isAddCache(targetName, methodName)) {
            // 跳过缓存返回结果
            return invocation.proceed();
        }
        Object[] arguments = invocation.getArguments();
        String key = getCacheKey(targetName, methodName, arguments);
        System.out.println("key=" + key);
        log.debug("reidsKey----------------------->" + key);
        try {
            // 判断是否有缓存
            boolean f = redisUtil.exists(key);
            if (f) {
                log.info("从缓存中用取值！！！");
                return redisUtil.get(key);
//                Object o = redisUtil.get(key);
//                String listStr = (String) o;
//                String[] split = listStr.split(",");
//                ArrayList<String> userList = Lists.newArrayList(split);
//                return userList;
            }
            // 写入缓存
            value = invocation.proceed();
            if (value != null) {
                final String tkey = key;
                final Object tvalue = value;//将用户存入redis中
//                final String join = Joiner.on(",").join((List) value);
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        redisUtil.set(tkey, tvalue, Long.parseLong(defaultCacheExpireTime));
                    }
                }).start();
            }
        } catch (Exception e) {
            e.printStackTrace();
            if (value == null) {
                return invocation.proceed();
            }
        }
        return value;
    }

    /**
     * 是否加入缓存
     *
     * @return
     */
    private boolean isAddCache(String targetName, String methodName) {
        boolean flag = true;
        boolean b = targetNamesList.contains(targetName) || methodNamesList.contains(methodName);
        if (b) {
            flag = false;
        }
        return flag;
    }

    /**
     * 创建缓存key
     *
     * @param targetName
     * @param methodName
     * @param arguments
     */
    private String getCacheKey(String targetName, String methodName,
                               Object[] arguments) {
        StringBuffer sbu = new StringBuffer();
        sbu.append(targetName).append("_").append(methodName);
        if ((arguments != null) && (arguments.length != 0)) {
            for (int i = 0; i < arguments.length; i++) {
                sbu.append("_").append(arguments[i]);
            }
        }
        return sbu.toString();
    }

    public void setRedisUtil(RedisUtil redisUtil) {
        this.redisUtil = redisUtil;
    }

    public void setTargetNamesList(List<String> targetNamesList) {
        this.targetNamesList = targetNamesList;
    }

    public void setMethodNamesList(List<String> methodNamesList) {
        this.methodNamesList = methodNamesList;
    }

    public void setDefaultCacheExpireTime(String defaultCacheExpireTime) {
        this.defaultCacheExpireTime = defaultCacheExpireTime;
    }
}
